fix: add back sonarcloud.yml for cpri sonar action (DCD-5125) - #422
Conversation
|
🤖 Hi @LukasKuzavas, I've received your request, and I'm working on it now! You can track my progress in the logs for more details. |
There was a problem hiding this comment.
This pull request restores the sonarcloud.yml workflow, which is used for the sonar job in CPRI. Overall, the workflow structure is well-defined and follows modern GitHub Actions conventions, but it introduces command/script injection vulnerabilities by directly interpolating dynamic inputs and secrets in shell scripts.
🔍 General Feedback
- Security Best Practices: Always prefer mapping inputs and secrets to environment variables via the
env:block in steps, referencing them with$VARIABLEinstead of direct workflow/secret context interpolation (${{ ... }}) in inline bash scripts. This prevents potential script injections. - Resilience: For highly reusable workflows, consider using
if-no-files-found: warninstead oferrorduring artifact uploads to allow successful runs for different callers that might lack specific optional subfolders.
| - name: Upload Sonar inputs | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: ${{ env.SONAR_ARTIFACT_NAME }} | ||
| retention-days: 1 | ||
| if-no-files-found: error |
There was a problem hiding this comment.
Using if-no-files-found: error in shared reusable workflows can cause premature build failures for caller repositories that do not produce all listed paths (such as test-results, jacoco, or classes folders). Setting this to warn prevents builds from failing while still alerting developers via the action logs if files are missing.
Remediation:
Change if-no-files-found to warn to make the artifact upload robust and tolerant to missing build outputs.
| - name: Upload Sonar inputs | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ env.SONAR_ARTIFACT_NAME }} | |
| retention-days: 1 | |
| if-no-files-found: error | |
| - name: Upload Sonar inputs | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ env.SONAR_ARTIFACT_NAME }} | |
| retention-days: 1 | |
| if-no-files-found: warn |
| - name: Restore gradle.properties and setup | ||
| working-directory: ${{ inputs.working-directory }} | ||
| shell: bash | ||
| env: | ||
| GRADLE_PROPERTIES: ${{ secrets.GRADLE_PROPERTIES }} | ||
| run: | | ||
| set -euo pipefail | ||
| mkdir -p "${HOME}/.gradle" | ||
| echo "GRADLE_USER_HOME=${HOME}/.gradle" >> "${GITHUB_ENV}" | ||
| { | ||
| echo "genesisArtifactoryUser=${{ secrets.JFROG_USERNAME }}" | ||
| echo "genesisArtifactoryPassword=${{ secrets.JFROG_PASSWORD }}" | ||
| echo "systemProp.org.gradle.internal.http.connectionTimeout=180000" | ||
| echo "systemProp.org.gradle.internal.http.socketTimeout=180000" | ||
| echo "dockerUrl=genesisglobal-docker-internal.jfrog.io" | ||
| echo "dockerUsername=${{ secrets.JFROG_USERNAME }}" | ||
| echo "dockerPassword=${{ secrets.JFROG_PASSWORD }}" | ||
| echo "dockerEmail=${{ secrets.JFROG_EMAIL }}" | ||
| echo "genesis-home=../.genesis-home" | ||
| echo "deploy-plugin-mode=local" | ||
| } > "${HOME}/.gradle/gradle.properties" | ||
| if [ -n "${GRADLE_PROPERTIES:-}" ]; then | ||
| printf '%s\n' "${GRADLE_PROPERTIES}" >> "${HOME}/.gradle/gradle.properties" | ||
| fi | ||
| if [ -f ./gradlew ]; then | ||
| chmod +x ./gradlew | ||
| fi | ||
| if [ -f "./${{ inputs.server-path }}/gradlew" ]; then | ||
| chmod +x "./${{ inputs.server-path }}/gradlew" | ||
| fi | ||
| if [ -d "./${{ inputs.server-path }}" ]; then | ||
| chmod -R +rx "./${{ inputs.server-path }}" | ||
| fi | ||
| cat "${HOME}/.gradle/gradle.properties" >> ./gradle.properties | ||
| RELEASE_VERSION="$(echo '${{ inputs.version }}' | sed 's/\//-/g')" | ||
| BUILD_FILE="${{ inputs.server-path }}/build.gradle.kts" | ||
| if [ -n "${RELEASE_VERSION}" ] && [ -f "${BUILD_FILE}" ]; then | ||
| sed -E -i "s/^[[:space:]]{4}version = \".+\"/ version = \"${RELEASE_VERSION}\"/g" "${BUILD_FILE}" | ||
| fi |
There was a problem hiding this comment.
Just like in the prepare-analysis job, directly interpolating secrets and inputs (such as ${{ secrets.JFROG_USERNAME }}, ${{ secrets.JFROG_PASSWORD }}, ${{ inputs.version }}, and ${{ inputs.server-path }}) into inline bash shell scripts is a serious security risk.
Remediation:
Map the inputs and secrets to environment variables in the step's env: context block, and reference them using shell environment variables.
| - name: Restore gradle.properties and setup | |
| working-directory: ${{ inputs.working-directory }} | |
| shell: bash | |
| env: | |
| GRADLE_PROPERTIES: ${{ secrets.GRADLE_PROPERTIES }} | |
| run: | | |
| set -euo pipefail | |
| mkdir -p "${HOME}/.gradle" | |
| echo "GRADLE_USER_HOME=${HOME}/.gradle" >> "${GITHUB_ENV}" | |
| { | |
| echo "genesisArtifactoryUser=${{ secrets.JFROG_USERNAME }}" | |
| echo "genesisArtifactoryPassword=${{ secrets.JFROG_PASSWORD }}" | |
| echo "systemProp.org.gradle.internal.http.connectionTimeout=180000" | |
| echo "systemProp.org.gradle.internal.http.socketTimeout=180000" | |
| echo "dockerUrl=genesisglobal-docker-internal.jfrog.io" | |
| echo "dockerUsername=${{ secrets.JFROG_USERNAME }}" | |
| echo "dockerPassword=${{ secrets.JFROG_PASSWORD }}" | |
| echo "dockerEmail=${{ secrets.JFROG_EMAIL }}" | |
| echo "genesis-home=../.genesis-home" | |
| echo "deploy-plugin-mode=local" | |
| } > "${HOME}/.gradle/gradle.properties" | |
| if [ -n "${GRADLE_PROPERTIES:-}" ]; then | |
| printf '%s\n' "${GRADLE_PROPERTIES}" >> "${HOME}/.gradle/gradle.properties" | |
| fi | |
| if [ -f ./gradlew ]; then | |
| chmod +x ./gradlew | |
| fi | |
| if [ -f "./${{ inputs.server-path }}/gradlew" ]; then | |
| chmod +x "./${{ inputs.server-path }}/gradlew" | |
| fi | |
| if [ -d "./${{ inputs.server-path }}" ]; then | |
| chmod -R +rx "./${{ inputs.server-path }}" | |
| fi | |
| cat "${HOME}/.gradle/gradle.properties" >> ./gradle.properties | |
| RELEASE_VERSION="$(echo '${{ inputs.version }}' | sed 's/\//-/g')" | |
| BUILD_FILE="${{ inputs.server-path }}/build.gradle.kts" | |
| if [ -n "${RELEASE_VERSION}" ] && [ -f "${BUILD_FILE}" ]; then | |
| sed -E -i "s/^[[:space:]]{4}version = \".+\"/ version = \"${RELEASE_VERSION}\"/g" "${BUILD_FILE}" | |
| fi | |
| - name: Restore gradle.properties and setup | |
| working-directory: ${{ inputs.working-directory }} | |
| shell: bash | |
| env: | |
| GRADLE_PROPERTIES: ${{ secrets.GRADLE_PROPERTIES }} | |
| INPUT_VERSION: ${{ inputs.version }} | |
| INPUT_SERVER_PATH: ${{ inputs.server-path }} | |
| JFROG_USERNAME: ${{ secrets.JFROG_USERNAME }} | |
| JFROG_PASSWORD: ${{ secrets.JFROG_PASSWORD }} | |
| JFROG_EMAIL: ${{ secrets.JFROG_EMAIL }} | |
| run: | | |
| set -euo pipefail | |
| mkdir -p "${HOME}/.gradle" | |
| echo "GRADLE_USER_HOME=${HOME}/.gradle" >> "${GITHUB_ENV}" | |
| { | |
| echo "genesisArtifactoryUser=${JFROG_USERNAME}" | |
| echo "genesisArtifactoryPassword=${JFROG_PASSWORD}" | |
| echo "systemProp.org.gradle.internal.http.connectionTimeout=180000" | |
| echo "systemProp.org.gradle.internal.http.socketTimeout=180000" | |
| echo "dockerUrl=genesisglobal-docker-internal.jfrog.io" | |
| echo "dockerUsername=${JFROG_USERNAME}" | |
| echo "dockerPassword=${JFROG_PASSWORD}" | |
| echo "dockerEmail=${JFROG_EMAIL}" | |
| echo "genesis-home=../.genesis-home" | |
| echo "deploy-plugin-mode=local" | |
| } > "${HOME}/.gradle/gradle.properties" | |
| if [ -n "${GRADLE_PROPERTIES:-}" ]; then | |
| printf '%s\n' "${GRADLE_PROPERTIES}" >> "${HOME}/.gradle/gradle.properties" | |
| fi | |
| if [ -f ./gradlew ]; then | |
| chmod +x ./gradlew | |
| fi | |
| if [ -f "./${INPUT_SERVER_PATH}/gradlew" ]; then | |
| chmod +x "./${INPUT_SERVER_PATH}/gradlew" | |
| fi | |
| if [ -d "./${INPUT_SERVER_PATH}" ]; then | |
| chmod -R +rx "./${INPUT_SERVER_PATH}" | |
| fi | |
| cat "${HOME}/.gradle/gradle.properties" >> ./gradle.properties | |
| RELEASE_VERSION="$(echo "${INPUT_VERSION}" | sed 's/\//-/g')" | |
| BUILD_FILE="${INPUT_SERVER_PATH}/build.gradle.kts" | |
| if [ -n "${RELEASE_VERSION}" ] && [ -f "${BUILD_FILE}" ]; then | |
| sed -E -i "s/^[[:space:]]{4}version = \".+\"/ version = \"${RELEASE_VERSION}\"/g" "${BUILD_FILE}" | |
| fi |
| - name: Restore gradle.properties and setup | ||
| working-directory: ${{ inputs.working-directory }} | ||
| shell: bash | ||
| env: | ||
| GRADLE_PROPERTIES: ${{ secrets.GRADLE_PROPERTIES }} | ||
| run: | | ||
| set -euo pipefail | ||
| mkdir -p "${HOME}/.gradle" | ||
| echo "GRADLE_USER_HOME=${HOME}/.gradle" >> "${GITHUB_ENV}" | ||
| { | ||
| echo "genesisArtifactoryUser=${{ secrets.JFROG_USERNAME }}" | ||
| echo "genesisArtifactoryPassword=${{ secrets.JFROG_PASSWORD }}" | ||
| echo "systemProp.org.gradle.internal.http.connectionTimeout=180000" | ||
| echo "systemProp.org.gradle.internal.http.socketTimeout=180000" | ||
| echo "dockerUrl=genesisglobal-docker-internal.jfrog.io" | ||
| echo "dockerUsername=${{ secrets.JFROG_USERNAME }}" | ||
| echo "dockerPassword=${{ secrets.JFROG_PASSWORD }}" | ||
| echo "dockerEmail=${{ secrets.JFROG_EMAIL }}" | ||
| echo "genesis-home=../.genesis-home" | ||
| echo "deploy-plugin-mode=local" | ||
| } > "${HOME}/.gradle/gradle.properties" | ||
| if [ -n "${GRADLE_PROPERTIES:-}" ]; then | ||
| printf '%s\n' "${GRADLE_PROPERTIES}" >> "${HOME}/.gradle/gradle.properties" | ||
| fi | ||
| chmod +x ./gradlew | ||
| chmod +x "./${{ inputs.server-path }}/gradlew" | ||
| chmod -R +rx "./${{ inputs.server-path }}" | ||
| cat "${HOME}/.gradle/gradle.properties" >> ./gradle.properties | ||
| RELEASE_VERSION="$(echo '${{ inputs.version }}' | sed 's/\//-/g')" | ||
| echo "RELEASE_VERSION=${RELEASE_VERSION}" >> "${GITHUB_ENV}" | ||
| BUILD_FILE="${{ inputs.server-path }}/build.gradle.kts" | ||
| if [ -n "${RELEASE_VERSION}" ] && [ -f "${BUILD_FILE}" ]; then | ||
| sed -E -i "s/^[[:space:]]{4}version = \".+\"/ version = \"${RELEASE_VERSION}\"/g" "${BUILD_FILE}" | ||
| fi |
There was a problem hiding this comment.
Directly interpolating secrets and inputs (such as ${{ secrets.JFROG_USERNAME }}, ${{ secrets.JFROG_PASSWORD }}, ${{ inputs.version }}, and ${{ inputs.server-path }}) into inline bash shell scripts is a serious security risk. If any of these values contain special characters (e.g. single/double quotes, spaces, semicolons, etc.), it could result in command/script injection, shell syntax errors, or accidental exposure in execution logs.
Remediation:
Always map workflow inputs and secrets to environment variables within the step's env: context block, and reference them using standard shell environment variable syntax ($VARIABLE_NAME). This ensures they are safely handled by the shell runner as values rather than raw script commands.
| - name: Restore gradle.properties and setup | |
| working-directory: ${{ inputs.working-directory }} | |
| shell: bash | |
| env: | |
| GRADLE_PROPERTIES: ${{ secrets.GRADLE_PROPERTIES }} | |
| run: | | |
| set -euo pipefail | |
| mkdir -p "${HOME}/.gradle" | |
| echo "GRADLE_USER_HOME=${HOME}/.gradle" >> "${GITHUB_ENV}" | |
| { | |
| echo "genesisArtifactoryUser=${{ secrets.JFROG_USERNAME }}" | |
| echo "genesisArtifactoryPassword=${{ secrets.JFROG_PASSWORD }}" | |
| echo "systemProp.org.gradle.internal.http.connectionTimeout=180000" | |
| echo "systemProp.org.gradle.internal.http.socketTimeout=180000" | |
| echo "dockerUrl=genesisglobal-docker-internal.jfrog.io" | |
| echo "dockerUsername=${{ secrets.JFROG_USERNAME }}" | |
| echo "dockerPassword=${{ secrets.JFROG_PASSWORD }}" | |
| echo "dockerEmail=${{ secrets.JFROG_EMAIL }}" | |
| echo "genesis-home=../.genesis-home" | |
| echo "deploy-plugin-mode=local" | |
| } > "${HOME}/.gradle/gradle.properties" | |
| if [ -n "${GRADLE_PROPERTIES:-}" ]; then | |
| printf '%s\n' "${GRADLE_PROPERTIES}" >> "${HOME}/.gradle/gradle.properties" | |
| fi | |
| chmod +x ./gradlew | |
| chmod +x "./${{ inputs.server-path }}/gradlew" | |
| chmod -R +rx "./${{ inputs.server-path }}" | |
| cat "${HOME}/.gradle/gradle.properties" >> ./gradle.properties | |
| RELEASE_VERSION="$(echo '${{ inputs.version }}' | sed 's/\//-/g')" | |
| echo "RELEASE_VERSION=${RELEASE_VERSION}" >> "${GITHUB_ENV}" | |
| BUILD_FILE="${{ inputs.server-path }}/build.gradle.kts" | |
| if [ -n "${RELEASE_VERSION}" ] && [ -f "${BUILD_FILE}" ]; then | |
| sed -E -i "s/^[[:space:]]{4}version = \".+\"/ version = \"${RELEASE_VERSION}\"/g" "${BUILD_FILE}" | |
| fi | |
| - name: Restore gradle.properties and setup | |
| working-directory: ${{ inputs.working-directory }} | |
| shell: bash | |
| env: | |
| GRADLE_PROPERTIES: ${{ secrets.GRADLE_PROPERTIES }} | |
| INPUT_VERSION: ${{ inputs.version }} | |
| INPUT_SERVER_PATH: ${{ inputs.server-path }} | |
| JFROG_USERNAME: ${{ secrets.JFROG_USERNAME }} | |
| JFROG_PASSWORD: ${{ secrets.JFROG_PASSWORD }} | |
| JFROG_EMAIL: ${{ secrets.JFROG_EMAIL }} | |
| run: | | |
| set -euo pipefail | |
| mkdir -p "${HOME}/.gradle" | |
| echo "GRADLE_USER_HOME=${HOME}/.gradle" >> "${GITHUB_ENV}" | |
| { | |
| echo "genesisArtifactoryUser=${JFROG_USERNAME}" | |
| echo "genesisArtifactoryPassword=${JFROG_PASSWORD}" | |
| echo "systemProp.org.gradle.internal.http.connectionTimeout=180000" | |
| echo "systemProp.org.gradle.internal.http.socketTimeout=180000" | |
| echo "dockerUrl=genesisglobal-docker-internal.jfrog.io" | |
| echo "dockerUsername=${JFROG_USERNAME}" | |
| echo "dockerPassword=${JFROG_PASSWORD}" | |
| echo "dockerEmail=${JFROG_EMAIL}" | |
| echo "genesis-home=../.genesis-home" | |
| echo "deploy-plugin-mode=local" | |
| } > "${HOME}/.gradle/gradle.properties" | |
| if [ -n "${GRADLE_PROPERTIES:-}" ]; then | |
| printf '%s\n' "${GRADLE_PROPERTIES}" >> "${HOME}/.gradle/gradle.properties" | |
| fi | |
| chmod +x ./gradlew | |
| chmod +x "./${INPUT_SERVER_PATH}/gradlew" | |
| chmod -R +rx "./${INPUT_SERVER_PATH}" | |
| cat "${HOME}/.gradle/gradle.properties" >> ./gradle.properties | |
| RELEASE_VERSION="$(echo "${INPUT_VERSION}" | sed 's/\//-/g')" | |
| echo "RELEASE_VERSION=${RELEASE_VERSION}" >> "${GITHUB_ENV}" | |
| BUILD_FILE="${INPUT_SERVER_PATH}/build.gradle.kts" | |
| if [ -n "${RELEASE_VERSION}" ] && [ -f "${BUILD_FILE}" ]; then | |
| sed -E -i "s/^[[:space:]]{4}version = \".+\"/ version = \"${RELEASE_VERSION}\"/g" "${BUILD_FILE}" | |
| fi |
https://genesisglobal.atlassian.net/browse/DCD-5125
sonarcloud.yml was being used for sonar job in cpri, adding back in and will take a look at a better plan for dealing with this action